package com.xh3140.android.widget.toast;


import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.core.content.res.ResourcesCompat;

import com.xh3140.android.widget.R;

@SuppressWarnings("unused")
public class Toast extends android.widget.Toast {
    @Nullable
    private static Toast INSTANCE;

    private final LinearLayoutCompat mRootView;
    private final AppCompatImageView mIconView;
    private final AppCompatTextView mMessageView;

    private enum Style {
        NORMAL(0, 0xFFFFFFFF, 0xFF535353),
        INFO(R.drawable.ic_toast_info, 0xFFFFFFFF, 0xFF3F51B5),
        SUCCESS(R.drawable.ic_toast_success, 0xFFFFFFFF, 0xFF388E3C),
        WARNING(R.drawable.ic_toast_warning, 0xFFFFFFFF, 0xFFFFA900),
        ERROR(R.drawable.ic_toast_error, 0xFFFFFFFF, 0xFFFD4C5B);

        @DrawableRes
        public final int icon;

        @ColorInt
        public final int textColor;

        @ColorInt
        public final int backgroundColor;

        Style(@DrawableRes int icon, @ColorInt int textColor, @ColorInt int backgroundColor) {
            this.icon = icon;
            this.textColor = textColor;
            this.backgroundColor = backgroundColor;
        }
    }

    private Toast(@NonNull Context context) {
        super(context);
        mRootView = createRootView(context);
        mIconView = createIconView(context);
        mMessageView = createMessageView(context);
        mRootView.addView(mIconView);
        mRootView.addView(mMessageView);
    }

    @NonNull
    public LinearLayoutCompat getRootView() {
        return mRootView;
    }

    @NonNull
    public AppCompatImageView getIconView() {
        return mIconView;
    }

    @NonNull
    public AppCompatTextView getMessageView() {
        return mMessageView;
    }

    @NonNull
    private static LinearLayoutCompat createRootView(@NonNull Context context) {
        final LinearLayoutCompat rootView = new LinearLayoutCompat(context);
        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        rootView.setLayoutParams(layoutParams);
        final int padding4 = (int) (4 * context.getResources().getDisplayMetrics().density + 0.5f);
        final int padding8 = (int) (8 * context.getResources().getDisplayMetrics().density + 0.5f);
        rootView.setPaddingRelative(padding8, padding4, padding8, padding4);
        rootView.setOrientation(LinearLayoutCompat.HORIZONTAL);
        return rootView;
    }

    @NonNull
    private static AppCompatImageView createIconView(@NonNull Context context) {
        final AppCompatImageView iconView = new AppCompatImageView(context);
        final int size = (int) (24 * context.getResources().getDisplayMetrics().density + 0.5f);
        final LinearLayoutCompat.LayoutParams layoutParams = new LinearLayoutCompat.LayoutParams(size, size);
        layoutParams.gravity = Gravity.CENTER_VERTICAL;
        iconView.setLayoutParams(layoutParams);
        return iconView;
    }


    @NonNull
    private static AppCompatTextView createMessageView(@NonNull Context context) {
        final AppCompatTextView messageView = new AppCompatTextView(context);
        final LinearLayoutCompat.LayoutParams layoutParams = new LinearLayoutCompat.LayoutParams(LinearLayoutCompat.LayoutParams.WRAP_CONTENT, LinearLayoutCompat.LayoutParams.WRAP_CONTENT);
        layoutParams.gravity = Gravity.CENTER_VERTICAL;
        messageView.setLayoutParams(layoutParams);
        final int padding = (int) (8 * context.getResources().getDisplayMetrics().density + 0.5f);
        messageView.setPaddingRelative(padding, padding, padding, padding);
        messageView.setGravity(Gravity.CENTER);
        messageView.setTypeface(Typeface.create("sans-serif-condensed", Typeface.NORMAL));
        return messageView;
    }

    //====================================================================================================================================================
    public static Toast normal(@NonNull Context context, @NonNull String message) {
        return normal(context, message, Toast.LENGTH_SHORT, true);
    }

    public static Toast normal(@NonNull Context context, @NonNull String message, boolean withIcon) {
        return normal(context, message, Toast.LENGTH_SHORT, withIcon);
    }

    public static Toast normal(@NonNull Context context, @NonNull String message, int duration) {
        return normal(context, message, duration, true);
    }

    public static Toast normal(@NonNull Context context, @NonNull String message, int duration, boolean withIcon) {
        return custom(context, message, withIcon ? Style.NORMAL.icon : 0, Style.NORMAL.textColor, Style.NORMAL.backgroundColor, duration);
    }

    //====================================================================================================================================================
    public static Toast info(@NonNull Context context, @NonNull String message) {
        return info(context, message, Toast.LENGTH_SHORT, true);
    }

    public static Toast info(@NonNull Context context, @NonNull String message, boolean withIcon) {
        return info(context, message, Toast.LENGTH_SHORT, withIcon);
    }

    public static Toast info(@NonNull Context context, @NonNull String message, int duration) {
        return info(context, message, duration, true);
    }

    public static Toast info(@NonNull Context context, @NonNull String message, int duration, boolean withIcon) {
        return custom(context, message, withIcon ? Style.INFO.icon : 0, Style.INFO.textColor, Style.INFO.backgroundColor, duration);
    }

    //====================================================================================================================================================
    public static Toast success(@NonNull Context context, @NonNull String message) {
        return success(context, message, Toast.LENGTH_SHORT, true);
    }

    public static Toast success(@NonNull Context context, @NonNull String message, boolean withIcon) {
        return success(context, message, Toast.LENGTH_SHORT, withIcon);
    }

    public static Toast success(@NonNull Context context, @NonNull String message, int duration) {
        return success(context, message, duration, true);
    }

    public static Toast success(@NonNull Context context, @NonNull String message, int duration, boolean withIcon) {
        return custom(context, message, withIcon ? Style.SUCCESS.icon : 0, Style.SUCCESS.textColor, Style.SUCCESS.backgroundColor, duration);
    }

    //====================================================================================================================================================
    public static Toast warning(@NonNull Context context, @NonNull String message) {
        return warning(context, message, Toast.LENGTH_SHORT, true);
    }

    public static Toast warning(@NonNull Context context, @NonNull String message, boolean withIcon) {
        return warning(context, message, Toast.LENGTH_SHORT, withIcon);
    }

    public static Toast warning(@NonNull Context context, @NonNull String message, int duration) {
        return warning(context, message, duration, true);
    }

    public static Toast warning(@NonNull Context context, @NonNull String message, int duration, boolean withIcon) {
        return custom(context, message, withIcon ? Style.WARNING.icon : 0, Style.WARNING.textColor, Style.WARNING.backgroundColor, duration);
    }

    //====================================================================================================================================================
    public static Toast error(@NonNull Context context, @NonNull String message) {
        return error(context, message, Toast.LENGTH_SHORT, true);
    }

    public static Toast error(@NonNull Context context, @NonNull String message, boolean withIcon) {
        return error(context, message, Toast.LENGTH_SHORT, withIcon);
    }

    public static Toast error(@NonNull Context context, @NonNull String message, int duration) {
        return error(context, message, duration, true);
    }

    public static Toast error(@NonNull Context context, @NonNull String message, int duration, boolean withIcon) {
        return custom(context, message, withIcon ? Style.ERROR.icon : 0, Style.ERROR.textColor, Style.ERROR.backgroundColor, duration);
    }

    //====================================================================================================================================================
    public static Toast custom(@NonNull Context context, @NonNull String message, @DrawableRes int iconRes, @ColorInt int textColor, @ColorInt int backgroundColor) {
        return custom(context, message, iconRes, textColor, backgroundColor, Toast.LENGTH_SHORT);
    }

    public static Toast custom(@NonNull Context context, @NonNull String message, @Nullable Drawable icon, @ColorInt int textColor, @ColorInt int backgroundColor) {
        return custom(context, message, icon, textColor, backgroundColor, Toast.LENGTH_SHORT);
    }

    public static Toast custom(@NonNull Context context, @NonNull String message, @DrawableRes int iconRes, @ColorInt int textColor, @ColorInt int backgroundColor, int duration) {
        try {
            final Drawable icon = ResourcesCompat.getDrawable(context.getResources(), iconRes, context.getTheme());
            return custom(context, message, icon, textColor, backgroundColor, duration);
        } catch (Resources.NotFoundException e) {
            return custom(context, message, null, textColor, backgroundColor, duration);
        }
    }

    public static Toast custom(@NonNull Context context, @NonNull String message, @Nullable Drawable icon, @ColorInt int textColor, @ColorInt int backgroundColor, int duration) {
        if (INSTANCE != null) {
            INSTANCE.cancel();
        }
        INSTANCE = new Toast(context);
        final int radius = (int) (24 * context.getResources().getDisplayMetrics().density + 0.5f);
        final GradientDrawable drawable = new GradientDrawable();
        drawable.setCornerRadius(radius);
        drawable.setColor(backgroundColor);
        INSTANCE.mRootView.setBackground(drawable);
        if (icon == null) {
            INSTANCE.mIconView.setVisibility(View.GONE);
        } else {
            INSTANCE.mIconView.setImageDrawable(icon);
        }
        INSTANCE.mMessageView.setText(message);
        INSTANCE.mMessageView.setTextColor(textColor);
        INSTANCE.setView(INSTANCE.mRootView);
        INSTANCE.setDuration(duration);
        return INSTANCE;
    }
}
